//
//  WalletService.swift
//  SCA
//
//  Created by tjun on 2025/9/7.
//

import Foundation

struct SwapData {
    var fromList: [SwapCoinModel]
    var defaultFrom: String
    var defaultTo: String
    let multiplier: [String: Any]
}

class WalletService {
    
    static func loadWalletInfo(success: ((WalletInfo) -> Void)? = nil, failure: ((_ error: Error) -> Void)? = nil) {
        
        let handleWalletInfo: (Any) -> Void = { data in
            
            guard let result = data as? [String: Any],
                  let wallet = result["wallet"] as? [String: Any],
                  let icons = result["icon"] as? [String: String],
                  let menus = result["menu"] as? [String: Any],
                  let mainMenu = result["main_menu"] as? [String: Any]
            else {
                return
            }
            
            let coins = wallet.keys.sorted()  // 按字母顺序排序
            printf("coins=\(coins)")
            
            var coinModels: [WalletCoinModel] = []
            
            for coinKey in coins {
                guard let coinData = wallet[coinKey] as? [String: Any] else { continue }
                
                let coinIcon = icons[coinKey] ?? ""
                let menu = menus[coinKey] as? [String: Any]
                let canTransfer = menu?.boolValue("transfer") ?? false
                let canWithdraw = menu?.boolValue("withdraw") ?? false
                
                // info 转换成[String: String]
                var stringInfo: [String: String] = [:]
                for (k, v) in coinData {
                    stringInfo[k] = "\(v)"
                }

                let coinModel = WalletCoinModel(coin: coinKey, info: stringInfo, coinUrl: coinIcon, transfer: canTransfer, withdraw: canWithdraw)
                coinModels.append(coinModel)
            }
            
            let total = result.stringValue("total")
            let total_disp = result.stringValue("total_disp")
            let deposit = mainMenu.boolValue("deposit")
            let withdraw = mainMenu.boolValue("withdraw")
            let transfer = mainMenu.boolValue("transfer")
            let swap = mainMenu.boolValue("swap")
            
            let sortModels = coinModels.sorted { $0.coinName > $1.coinName }
            
            let walletInfo = WalletInfo(
                coinModels: sortModels,
                total: total,
                total_disp: total_disp,
                deposit: deposit,
                withdraw: withdraw,
                transfer: transfer,
                swap: swap
            )
            
            success?(walletInfo)
            
            if let jsonString = result.toJSONString() {
                let walletModuleModel = WalletModuleModel.current
                walletModuleModel.walletInfo = jsonString
                walletModuleModel.asyncInsertOrReplace()
            }
        }
        
        let walletModuleModel = WalletModuleModel.current
        if let dict = walletModuleModel.walletInfo.toObject() as? [String: Any] {
            handleWalletInfo(dict)
        }
        
        NetworkManager.shared.post(url: APIEndpoint.walletInfo, parameters: nil, success: { data in
            handleWalletInfo(data)
        }, failure: failure)
    }
 
    
    static func loadWalletDetail(coin: String,
                                 pageIndex: Int = 1,
                                 success: (([TransactionRecordModel], String, Int) -> Void)? = nil,
                                 failure: ((_ error: Error) -> Void)? = nil) {
        
        NetworkManager.shared.post(url: String(format: APIEndpoint.walletDetails, coin),
                                   parameters: nil,
                                   success: { resultData in
            guard let result = resultData as? [String: Any],
                  let datalist = result["datalist"] as? [String: Any],
                  let data = datalist["data"] as? [String: Any],
                  let accountDict = datalist["account"] as? [String: Any],
                  let totalAccount = accountDict["total"] as? String,
                  let total = datalist["total_record"] as? Int else {
                return
            }
        
            
            let models: [TransactionRecordModel] = data.values.compactMap { value in
                guard let dict = value as? [String: Any] else { return nil }
                
                let type = dict.stringValue("type")
                let typeDisp = dict.stringValue("type_disp")
                let Id = dict.intValue("id")
                let account = dict.stringValue("amount")
                let amountDisp = dict.stringValue("amount_disp")
                let dateString = dict.stringValue("cdate")
                let op = dict.stringValue("op")
                
                let date = formatDate(dateString)
                return TransactionRecordModel(Id: Id,
                                              type: type,
                                              typeDisp: typeDisp,
                                              amount: account,
                                              amountDisp: amountDisp,
                                              date: date,
                                              op: op)
            }
            
            let sortedModels = models.sorted { $0.Id > $1.Id }
            success?(sortedModels, totalAccount, total)
        }, failure: failure)
    }
    
    
    static func transaction(coinName: String,
                            amount: String,
                            pinCcode: String,
                            username: String,
                            otp: String,
                            complation: ((String?, Error?) -> Void)? = nil) {
        NetworkManager.shared.post(url: String(format: APIEndpoint.walletTransaction, coinName), parameters: [
            "username": username,
            "amount": amount,
            "otp": otp,
            "pin_code": pinCcode,
        ], success: { resultData in
            guard let result = resultData as? [String: Any],
                  let success = result["success"] as? Bool,
                  let amount = result["amount"] as? String else {
                complation?(nil, SCAError.dataException)
                return
            }
            if success {
                complation?(amount, nil)
            } else {
                complation?(nil, SCAError.universal("转账失败".localizedString))
            }
        }) { error in
            complation?(nil, error)
        }
    }
    
    static func transactionCheckUsername(coinName: String, username: String, complation: ((Bool) -> Void)? = nil) {
        NetworkManager.shared.post(url: String(format: APIEndpoint.walletCheckUsername, coinName.lowercased()), parameters: [
            "username": username,
        ], success: { resultData in
            guard let result = resultData as? [String: Any],
                  let status = result["status"] as? Bool else {
                return
            }
            complation?(status)
        }) { error in
            complation?(false)
        }
    }
    
    static func loadSwapData(completion: @escaping (SwapData?, Error?) -> Void) {
        
        let handleSwapData: (Any) -> Void = { resultData in
            guard
                let result = resultData as? [String: Any],
                let conf = result["conf"] as? [String: Any],
                let multiplier = conf["multiplier"] as? [String: Any],
                let defaultFromWallet = result["default_from_wallet"] as? String,
                let defaultToWallet = result["default_to_wallet"] as? String,
                let fromWalletOption = conf["from_wallet_option"] as? [String: String],
                let toWalletOption = conf["to_wallet_option"] as? [String: Any],
                let fromWalletInfo = conf["from_wallet"] as? [String: Any],
                let toWalletInfo = conf["to_wallet"] as? [String: Any]
            else {
                completion(nil, nil)
                return
            }
            
            var fromList: [SwapCoinModel] = []
            
            for (fromCoin, fromCoinName) in fromWalletOption {
                
                let fromModel = SwapCoinModel(coinName: fromCoinName, coin: fromCoin)
                
                // 填充 from 详情
                if let info = fromWalletInfo[fromCoin] as? [String: Any] {
                    
                    fromModel.min = info.stringValue("min")
                    fromModel.decimal = info.stringValue("decimal")
                    fromModel.swapDecimal = info.stringValue("swap_decimal")
                    fromModel.fee = info.stringValue("fee")
                    fromModel.feeDisp = info.stringValue("fee_disp")
                    fromModel.title = info.stringValue("title")
                    fromModel.balance = info.stringValue("balance")
                    fromModel.balanceDisp = info.stringValue("balance_disp")
                    fromModel.rate = info.stringValue("rate")
                }
                
                // 子币种 to 列表
                if let toOptions = toWalletOption[fromCoin] as? [String: String] {
                    var subList: [SwapCoinModel] = []
                    
                    for (toCoin, toCoinName) in toOptions {
                        
                        let toModel = SwapCoinModel(coinName: toCoinName, coin: toCoin)
                        
                        // 填充 to 详情
                        if let info = toWalletInfo[toCoin] as? [String: Any] {
                            
                            toModel.min = info.stringValue("min")
                            toModel.decimal = info.stringValue("decimal")
                            toModel.swapDecimal = info.stringValue("swap_decimal")
                            toModel.fee = info.stringValue("fee")
                            toModel.feeDisp = info.stringValue("fee_disp")
                            toModel.title = info.stringValue("title")
                            toModel.balance = info.stringValue("balance")
                            toModel.balanceDisp = info.stringValue("balance_disp")
                            toModel.rate = info.stringValue("rate")
                          
                        }
                        
                        subList.append(toModel)
                    }
                    
                    fromModel.subCoinModels = subList.sorted { $0.coinName > $1.coinName }
                }
                
                fromList.append(fromModel)
            }
            
            fromList.sort { $0.coinName > $1.coinName }
            
            let swapData = SwapData(fromList: fromList, defaultFrom: defaultFromWallet, defaultTo: defaultToWallet, multiplier: multiplier)
            completion(swapData, nil)
            
            if let jsonString = result.toJSONString() {
                let walletModuleModel = WalletModuleModel.current
                walletModuleModel.swapData = jsonString
                walletModuleModel.asyncInsertOrReplace()
            }
        }
 
        let walletModuleModel = WalletModuleModel.current
        if let dict = walletModuleModel.swapData.toObject() as? [String: Any] {
            handleSwapData(dict)
        }
        
        NetworkManager.shared.post(url: APIEndpoint.walletSwapGlobal, parameters: [
            "step": "ini", "fid": "\(Snowflake.shared.nextId())"
        ], success: { resultData in
            handleSwapData(resultData)
        }, failure: { error in
            completion(nil, error)
        })
    }
    
    static func swap(fromCoin: String, toCoin: String, amount: String, pinCode: String, complation: ((String?, Error?) -> Void)? = nil) {
        
        var parameters: [String: Any] = [:]
        parameters["from_wallet"] = fromCoin
        parameters["to_wallet"] = toCoin
        parameters["pin_code"] = pinCode
        parameters["amount"] = amount
        parameters["fid"] = "\(Snowflake.shared.nextId())"

        NetworkManager.shared.post(url: APIEndpoint.walletSwapGlobal, parameters: parameters, success: { resultData in
            guard let result = resultData as? [String: Any],
                  let success = result["success"] as? Bool,
                  let amount = result["amount"] as? String else {
                complation?(nil, SCAError.dataException)
                return
            }
            if success {
                complation?(amount, nil)
            } else {
                complation?(nil, SCAError.universal("兑换失败".localizedString))
            }
        }) { error in
            complation?(nil, error)
        }
    }
    
    static func loadRechargeData(coin: String, complation: (([RechargeModel]?, Error?) -> Void)? = nil) {
        
        let handleRechargeData: (Any) -> Void = { data in
          
            guard let result = data as? [String: Any],
                  let success = result["success"] as? Bool,
                  let addressData = result["address"] as? [String: Any] else {
                complation?(nil, SCAError.dataException)
                return
            }
            
            if success {
                var models: [RechargeModel] = []
                
                for (key, dict) in addressData {
                    guard let coinInfo = dict as? [String: Any],
                          let conf = coinInfo["conf"] as? [String: Any],
                          let description = conf["description"] as? [String: Any]  else { continue }
                    
                    let address = coinInfo.stringValue("address")
                    let detail = description.stringValue("est") + "\n" + description.stringValue("min")
                    let notice = coinInfo.stringValue("notice")
                    let qr_link = coinInfo.stringValue("qr_link")

                    models.append(RechargeModel(network: key, address: address, detail: detail, hint: notice, qrCodeLink: qr_link))
                }
                
                let sortModels = models.sorted { $0.network < $1.network }
                printf("sortModels=\(sortModels)")
                complation?(sortModels, nil)
                
                
                if let jsonString = result.toJSONString() {
                    let walletModuleModel = WalletModuleModel.current
                    walletModuleModel.walletDepositUsdt = jsonString
                    walletModuleModel.asyncInsertOrReplace()
                }
                
            } else {
                complation?(nil, SCAError.dataException)
            }
        }
        
        let walletModuleModel = WalletModuleModel.current
        if let dict = walletModuleModel.walletDepositUsdt.toObject() as? [String: Any] {
            handleRechargeData(dict)
        }
        
        NetworkManager.shared.post(url: String(format: APIEndpoint.walletRecharge, coin), parameters: nil, success: { resultData in
            handleRechargeData(resultData)
        }) { error in
            complation?(nil, error)
        }
    }
}
